'use strict';

const Controller = require('../lib/controller');

module.exports = class CommentController extends Controller {
  async index() {
    switch (String(this.ctx.request.query.act)) {
      case 'save':
        if (this.ctx.app.theCache.settings.enableComment == 1) {
          await this.commentSave();
        } else {
          await this.ctx.response.redirectMessage(
            this.ctx.__('error'),
            this.ctx.__('comment_disabled'),
            this.ctx.__('goback'),
            'javascript:window.history.back();',
            false,
            'errorbox'
          );
        }
        break;
      case 'edit':
        await this.commentEdit(false);
        break;
      case 'update':
        await this.commentEdit(true);
        break;
      case 'delete':
        await this.commentDelete();
        break;
      default:
        // View Comment List
        await this.commentList();
    }
  }

  // Output Comment List ////////////////////////////////////////////////////////
  async commentList() {
    let sqlWHERE = '';
    let strURLPrefix = '?';
    let arrKeywords = '';

    // Check current page number
    let pageIndex = this.ctx.helper.checkInt(this.ctx.request.query.page);
    pageIndex = Math.max(1, pageIndex);

    // Check category id
    const categoryId = this.ctx.helper.checkInt(this.ctx.request.query.cat);
    if (categoryId > 0) {
      sqlWHERE += ' AND tLog.log_catID=' + categoryId;
      strURLPrefix += strURLPrefix == '?' ? '' : '&amp;';
      strURLPrefix += 'cat=' + categoryId;
    }


    // Check user id
    const userId = this.ctx.helper.checkInt(this.ctx.request.query.user);
    if (userId > 0) {
      sqlWHERE += ' AND tComm.comm_authorID=' + userId;
      strURLPrefix += strURLPrefix == '?' ? '' : '&amp;';
      strURLPrefix += 'user=' + userId;
    }

    // Check if has search keywords
    if (this.ctx.request.query.q) {
      arrKeywords = this.ctx.request.query.q.split(' ');
      for (let i = 0; i < this.ctx.request.query.q.length; i++) {
        if (this.ctx.helper.lengthW(arrKeywords[i]) > 2) {
          sqlWHERE += " AND tComm.comm_content LIKE '%" + this.ctx.helper.checkStr(arrKeywords[i]) + "%'";
        }
      }
      strURLPrefix += strURLPrefix == '?' ? '' : '&amp;';
      strURLPrefix += 'q=' + this.ctx.request.query.q;
    }

    // Check if has highlight keywords
    if (this.ctx.request.query.hl) {
      arrKeywords = this.ctx.request.query.hl.split(' ');
      strURLPrefix += strURLPrefix == '?' ? '' : '&amp;';
      strURLPrefix += 'hl=' + this.ctx.request.query.hl;
    }

    // Check for Hidden category display rights
    if (this.ctx.theUser.rights.view < 2) {
      sqlWHERE += ' AND tLog.log_mode=1';
      for (let i = 0; i < this.ctx.app.theCache.categories.length; i++) {
        if (this.ctx.app.theCache.categories[i].hidden) {
          sqlWHERE += ' AND tLog.log_catid<>' + this.ctx.app.theCache.categories[i].id;
        }
      }
    }

    // Load comments from DB
    let comments;
    let entryCount;
    const entryPerPage = this.ctx.app.theCache.settings.listEntryPerPage;
    const strSQL = 'SELECT tComm.*, tLog.log_authorID, tLog.log_title FROM blog_article tLog, blog_comment tComm WHERE tLog.log_id=tComm.log_id ' + sqlWHERE + ' ORDER BY tComm.comm_postTime DESC';

    comments = this.ctx.app.connBlog.query(strSQL, entryPerPage, pageIndex, false);
    if (!comments) {
      comments = [];
      entryCount = 0;
    } else {
      entryCount = this.ctx.app.connBlog.recordCount;
      for (let i = 0; i < comments.length; i++) {
        comments[i] = {
          id: comments[i].comm_id,
          log_id: comments[i].log_id,
          log_title: comments[i].log_title,
          log_authorID: comments[i].log_authorid,
          author: comments[i].comm_author,
          authorID: comments[i].comm_authorid,
          content: comments[i].comm_content,
          hidden: comments[i].comm_hidden,
          postTime: new Date(Number(comments[i].comm_posttime)),
          ubbFlags: comments[i].comm_ubbflags,
          editMark: comments[i].comm_editmark,
          IP: comments[i].comm_ip,
        };
      }
    }

    // Output Comment List
    const data = {
      strTitle: this.ctx.__('comments'),
      comments,
      intEntryCount: entryCount,
      intEntryPerPage: entryPerPage,
      intCurrentPage: pageIndex,
      intCategory: categoryId,
      strURLPrefix,
      arrKeywords,
      input: this.ctx.request.query,
    };

    await this.ctx.render('comment/comment.ejs', data);

  }

  // Save New Comment ///////////////////////////////////////////////////////////////////////////////
  async commentSave() {
    if (this.ctx.theUser.rights.post < 1 || this.ctx.app.theCache.settings.enableComment == 0 || !this.ctx.session.lbsSecurityCode) {
      // Check User Right - without DB Query
      return await this.ctx.response.redirectMessage(
        this.ctx.__('error'),
        this.ctx.__('no_rights'),
        this.ctx.__('goback'),
        'javascript:window.history.back();',
        false,
        'errorbox'
      );
    }

    if ((new Date()) - this.ctx.session.FloodControl < this.ctx.app.theCache.settings.minPostDuration * 1000) {
      // Check if user is banned for Spam
      this.ctx.session.FloodControl = new Date();
      return await this.ctx.response.redirectMessage(
        this.ctx.__('error'),
        this.ctx.__('flood_control'),
        this.ctx.__('goback'),
        'javascript:window.history.back();',
        false,
        'errorbox'
      );
    }
    let strError = '';
    let bCheckCode = true;

    // For guest user group
    if (!this.ctx.theUser.loggedIn) {
      if (this.ctx.request.body.comm_register == 'true') {
        // Do register
        this.ctx.request.body.username = this.ctx.request.body.comm_username;
        this.ctx.request.body.password = this.ctx.request.body.comm_password;
        this.ctx.request.body.repassword = this.ctx.request.body.comm_password;
        this.ctx.request.body.email = '';
        this.ctx.request.body.hideemail = true;
        const strErrorRegister = await this.ctx.theUser.register(true);
        if (strErrorRegister != false) {
          strError += strErrorRegister;
        } else {
          const tmpA = await this.ctx.app.connBlog.query("SELECT user_id FROM blog_user WHERE user_name='" + this.ctx.helper.checkStr(this.ctx.request.query.comm_username) + "'", 1, 1);
          if (tmpA && tmpA.length) this.ctx.theUser.id = tmpA[0].user_id;
        }
        bCheckCode = false; // Bypass the Security Code check below
      } else if (this.ctx.request.query.comm_password != undefined && this.ctx.request.query.comm_password != '') {
        // Do login
        const strErrorLogin = this.ctx.theUser.login(this.ctx.request.query.comm_username, this.ctx.request.query.comm_password, 1, true, this.ctx.request.query.scode);
        if (strErrorLogin != false) strError += strErrorLogin;
        bCheckCode = false; // Bypass the Security Code check below
      } else {
        // Check Username for Guest
        if (!this.ctx.request.body.comm_username || !this.ctx.helper.checkUsername(this.ctx.request.body.comm_username)) {
          strError += '<li>' + this.ctx.__('username_invalid') + '</li>';
        } else if (await this.ctx.app.connBlog.query("SELECT user_id FROM blog_user WHERE user_name='" + this.ctx.helper.checkStr(this.ctx.request.body.comm_username) + "'", 1, 1)) {
          strError += '<li>' + this.ctx.__('user_exist') + '</li>';
        }
        this.ctx.theUser.id = 0;
        this.ctx.theUser.username = this.ctx.request.body.comm_username;
      }
    }

    // Check for data
    strError += this.checkPostData(bCheckCode, true);

    // Check for ubbFlags
    const strUbbFlags = this.getUbbFlags();

    if (strError != '') {
      return await this.ctx.response.redirectMessage(
        this.ctx.__('error'),
        strError,
        this.ctx.__('goback'),
        'javascript:window.history.back();',
        false,
        'errorbox'
      );

    }
    const arrInsert = {
      log_id: this.ctx.request.body.logid,
      comm_content: this.ctx.request.body.message,
      comm_authorID: this.ctx.theUser.id,
      comm_author: this.ctx.theUser.username,
      comm_ubbFlags: strUbbFlags,
      comm_hidden: this.ctx.request.body.comm_hidden == 'true',
      comm_postTime: new Date(),
      comm_ip: this.ctx.theUser.IP,
    };
    await this.ctx.app.connBlog.insert('blog_comment', arrInsert);
    await this.ctx.app.connBlog.updateSQL('blog_article', 'log_commentCount=log_commentCount+1', 'log_id=' + this.ctx.request.query.logid);
    await this.ctx.app.connBlog.updateSQL('blog_user', 'user_commentCount=user_commentCount+1', 'user_id=' + this.ctx.theUser.id);
    await this.ctx.app.connBlog.updateSQL('blog_settings', 'set_value0=set_value0+1', "set_name='counterComment'");
    await this.ctx.app.theCache.updateArticleCounter(this.ctx.request.query.logid, 'comment', 1);
    await this.ctx.app.theCache.updateGlobalCounter('counterComment', 1);
    await this.ctx.app.theCache.loadComments();

    // Clean up to avoid abuse
    this.ctx.session.lbsSecurityCode = null;

    // Flood Control
    this.ctx.session.FloodControl = new Date();

    // Output ok message
    await this.ctx.response.redirectMessage(
      this.ctx.__('done'),
      this.ctx.__('comment_save_done'),
      this.ctx.__('redirect'),
      'article.asp?id=' + this.ctx.request.query.logid,
      true,
      'messagebox'
    );

  }

  // Check Post Form Data -----------------------
  async checkPostData(bCheckCode, bCheckArticle) {

    let strError = '';

    // Check Security Code
    if (this.ctx.app.theCache.settings.enableSecurityCode == 1 && bCheckCode && this.ctx.session.lbsSecurityCode != this.ctx.request.body.scode) {
      strError += '<li>' + this.ctx.__('scode_invalid') + '</li>';
    }

    // Check content
    this.ctx.request.body.message = this.ctx.helper.trim(this.ctx.request.body.message);
    if (!this.ctx.request.body.message) {
      strError += '<li>' + this.ctx.__('content_blank') + '</li>';
    } else {
      if (this.ctx.request.body.message.length > this.ctx.app.theCache.settings.maxCommentLength || this.ctx.request.body.message.length < 2) {
        strError += '<li>' + this.ctx.__('length_invalid') + '</li>';
      }
      if (this.ctx.helper.countURL(this.ctx.request.body.message) > this.ctx.app.theCache.settings.maxCommentURLCount) {
        strError += '<li>' + this.ctx.__('comment_url_count_block') + '</li>';
      }
      this.ctx.request.body.message = this.ctx.helper.wordFilter(this.ctx.request.body.message);
      if (!this.ctx.request.body.message) {
        strError += '<li>' + this.ctx.__('wordfilter_block') + '</li>';
      }

    }

    // Exit with error so we don't need to query the db any more
    if (strError != '' || !bCheckArticle) {
      return strError;
    }

    // Check if target article exists
    const theArticle = this.ctx.service.article;

    this.ctx.request.body.logid = this.ctx.helper.checkInt(this.ctx.request.body.logid);
    if (!this.ctx.request.body.logid) {
      strError = this.ctx.__('invalid_parameter');
    } else {
      if (await theArticle.load('log_catid, log_mode, log_locked', 'log_id=' + this.ctx.request.body.logid)) {
        strError = '';
      } else {
        strError = this.ctx.__('article_not_found');
      }
    }

    if (strError != '') {
      // Article not found
      return strError;
    }

    // Check article status for different user permissions
    if (theArticle.locked || theArticle.category.locked ||
      theArticle.category.hidden && this.ctx.theUser.rights.view < 2 ||
      theArticle.mode == 1 && this.ctx.theUser.rights.view < 1 ||
      theArticle.mode == 2 && (!this.ctx.theUser.loggedIn || this.ctx.theUser.rights.view < 1) ||
      theArticle.mode == 3 && (!this.ctx.theUser.loggedIn || this.ctx.theUser.rights.view < 2) ||
      theArticle.mode == 4 && (!this.ctx.theUser.loggedIn || this.ctx.theUser.rights.view < 3)
    ) {
      strError = '<li>' + this.ctx.__('no_rights') + '</li>';
    }

    return strError;

  }


  // Get ubbFlags String -----------------------
  async getUbbFlags() {
    let ubbFlags = '';
    ubbFlags += this.ctx.request.query.e_ubb === 'true' ? '1' : '0';
    ubbFlags += this.ctx.request.query.e_autourl === 'true' ? '1' : '0';
    ubbFlags += '2'; // bImage - always 2
    ubbFlags += '2'; // bMedia - always 2
    ubbFlags += this.ctx.request.query.e_smilies === 'true' ? '1' : '0';
    ubbFlags += '1'; // bTextBlock - always 1
    return ubbFlags;
  }

  // Edit Comment ///////////////////////////////////////////////////////////////////////////////////
  async commentEdit(bSave) {
    if (this.ctx.theUser.rights.edit < 1) {
      // Check User Right - without DB Query
      return await this.ctx.response.redirectMessage(
        this.ctx.__('error'),
        this.ctx.__('no_rights'),
        this.ctx.__('goback'),
        'javascript:window.history.back();',
        false,
        'errorbox'
      );
    }

    let strError = '';
    let arrData;

    this.ctx.request.query.id = this.ctx.helper.checkInt(this.ctx.request.query.id);
    if (!this.ctx.request.query.id) {
      strError = this.ctx.__('invalid_parameter');
    } else {
      // Check user right again
      arrData = await this.ctx.app.connBlog.query('SELECT tLog.log_id,tLog.log_authorID,tLog.log_title,tComm.comm_authorid,tComm.comm_content,tComm.comm_ubbFlags,tComm.comm_hidden FROM blog_article tLog,blog_comment tComm WHERE tLog.log_id=tComm.log_id AND tComm.comm_id=' + this.ctx.request.query.id, 1, 1);
      if (arrData) {
        arrData = arrData[0];
        if (this.ctx.theUser.id != arrData.log_authorid && this.ctx.theUser.id != arrData.comm_authorid && this.ctx.theUser.rights.edit < 2) {
          strError = this.ctx.__('no_rights');
        }
      } else {
        strError = this.ctx.__('comment_not_found');
      }
    }

    if (strError != '') {
      return await this.ctx.response.redirectMessage(
        this.ctx.__('error'),
        strError,
        this.ctx.__('goback'),
        'javascript:window.history.back();',
        false,
        'errorbox'
      );
    }

    if (!bSave) {
      // Output the Edit Form
      this.ctx.genSecurityCode();
      const data = {
        strTitle: this.ctx.__('edit_comment_on') + ': ' + arrData.log_title,
        strActionURL: '?act=update&id=' + this.ctx.request.query.id,
        strContent: arrData.comm_content,
        strUBBFlags: arrData.comm_ubbflags,
        bHidden: arrData.comm_hidden,
      };

      return await this.ctx.render('comment/editComment.ejs', data);
    }

    // Save changes
    strError = this.checkPostData(true, false);
    const strUbbFlags = this.getUbbFlags();

    if (strError != '') {
      return await this.ctx.response.redirectMessage(
        this.ctx.__('error'),
        strError,
        this.ctx.__('goback'),
        'javascript:window.history.back();',
        false,
        'errorbox'
      );
    }

    const arrUpdate = { comm_content: this.ctx.request.query.message,
      comm_ubbFlags: strUbbFlags,
      comm_hidden: this.ctx.request.query.comm_hidden == 'true',
      comm_ip: this.ctx.theUser.IP,
    };
    if (this.ctx.request.query.message != arrData.comm_content) {
      arrUpdate.comm_editMark = this.ctx.theUser.username + '$|$' + this.ctx.helper.getDateTimeString();
    }

    await this.ctx.app.connBlog.update('blog_comment', arrUpdate, { comm_id: this.ctx.request.query.id });
    await this.ctx.app.theCache.loadComments();

    // Clean up to avoid abuse
    this.ctx.session.lbsSecurityCode = null;
    // Output ok message
    await this.ctx.response.redirectMessage(
      this.ctx.__('done'),
      this.ctx.__('comment_save_done'),
      this.ctx.__('redirect'),
      'article.asp?id=' + arrData.log_id,
      true,
      'messagebox'
    );

  }

  // Delete Comment ///////////////////////////////////////////////////////////////////////////////////
  async commentDelete() {
    if (this.ctx.theUser.rights.delete < 1) {
      return await this.ctx.response.redirectMessage(
        this.ctx.__('error'),
        this.ctx.__('no_rights'),
        this.ctx.__('goback'),
        'javascript:window.history.back();',
        false,
        'errorbox'
      );
    }

    let strError = '';
    let arrData;

    this.ctx.request.query.id = this.ctx.helper.checkInt(this.ctx.request.query.id);
    if (!this.ctx.request.query.id) {
      strError = this.ctx.__('invalid_parameter');
    } else {
      // Check user right again
      arrData = await this.ctx.app.connBlog.query('SELECT tLog.log_id,tLog.log_authorID,tComm.comm_authorid FROM blog_article tLog,blog_comment tComm WHERE tLog.log_id=tComm.log_id AND tComm.comm_id=' + this.ctx.request.query.id, 1, 1);
      if (arrData) {
        arrData = arrData[0];
        if (this.ctx.theUser.id != arrData.log_authorid && this.ctx.theUser.id != arrData.comm_authorid && this.ctx.theUser.rights.delete < 2) {
          strError = this.ctx.__('no_rights');
        }
      } else {
        strError = this.ctx.__('comment_not_found');
      }
    }

    if (strError != '') {
      return await this.ctx.response.redirectMessage(
        this.ctx.__('error'),
        strError,
        this.ctx.__('goback'),
        'javascript:window.history.back();',
        false,
        'errorbox'
      );
    }

    await this.ctx.app.connBlog.doDelete('blog_comment', 'comm_id=' + this.ctx.request.query.id);
    await this.ctx.app.connBlog.updateSQL('blog_article', 'log_commentCount=log_commentCount-1', 'log_id=' + arrData.log_id);
    await this.ctx.app.connBlog.updateSQL('blog_user', 'user_commentCount=user_commentCount-1', 'user_id=' + arrData.comm_authorid);
    await this.ctx.app.connBlog.updateSQL('blog_settings', 'set_value0=set_value0-1', "set_name='counterComment'");
    await this.ctx.app.theCache.updateArticleCounter(arrData.log_id, 'comment', -1);
    await this.ctx.app.theCache.updateGlobalCounter('counterComment', -1);
    await this.ctx.app.theCache.loadComments();

    await this.ctx.response.redirectMessage(
      this.ctx.__('done'),
      this.ctx.__('comment_delete_done'),
      this.ctx.__('redirect'),
      'article.asp?id=' + arrData.log_id,
      true,
      'messagebox'
    );

  }

};
